; *** This is the CPU DIAGNOSTIC for the FOONLY F2 and F3 computers. *** CFDEF-IN: ;;;.REPEAT CFDEF-IN < 1 [ ;ONLY IF NOT ALREADY IN... F2SW = 0 ; this must be defined... XLIST .INSERT SWINIT.SLO .INSERT CFDEF.SLO ; get machine definition LIST : 2000 ; START ASSEMBLING INTO THIS ADDRESS ;;;];REPEAT CFDEF-IN = 0 START: ; FIRST, TEST JUMP TO SEE IF IT HANDLES TRUE/FALSE AND OBUS=0 ; CONDITIONS PROPERLY. JUMP [. + 1] $ ; ... HELP OPERATOR START FROM SWITCHES ... JUMP [.] COND [FALSE] $ ; FAILS IF COND FALSE DOESNT WORK JUMP [. + 2] COND [TRUE] $ JUMP [.] $ ; HERE IF PREVIOUS INST FALLS THRU ALU [-1] COND [OBUS=0] JUMP [.] $ ; TEST OBUS=0 CONDITION ALU [-1] COND [-OBUS=0] JUMP [. + 2] $ JUMP [.] $ ; PREV INST FALLS THRU IF -OBUS=0 DONT WORK ALU [0] COND [-OBUS=0] JUMP [.] $ ALU [0] COND [OBUS=0] JUMP [. + 2] $ JUMP [.] $ ; NOW, TEST Q REG TO SEE IF IT CAN HOLD ANYTHING ALU [0] DEST [Q] $ ; LOAD 0 INTO Q REG ALU [Q] COND [-OBUS=0] JUMP [.] $ ; HALTS IF Q/=0 ALU [-1] DEST [Q] $ ; LOAD -1 INTO Q ALU [Q] COND [OBUS=0] JUMP [.] $ ; HALTS IF Q=0 ; TRY USING THE ALU TO OPERATE ON CONTENTS OF Q ; AT THIS POINT Q=-1 ALU [NOTQ] DEST [Q] $ ; THIS ZEROS Q ALU [Q] COND [-OBUS=0] JUMP [.] $ ; CHECK TO BE SURE ITS 0 ALU [NOTQ] DEST [Q] $ ; THIS SETS Q=-1 ALU [NOTQ] COND [-OBUS=0] JUMP [.] $ ; NOT Q SHOULD NOW BE ZERO ALU [Q+1] DEST [Q] $ ALU [Q] COND [-OBUS=0] JUMP [.] $ ; SHOULD BE 0 ALU [Q-1] DEST [Q] $ ; SHOULD BE -1 ALU [NOTQ] COND [-OBUS=0] JUMP [.] $ ; THIS TIME, TRY ARITHMETICALLY MODIFYING Q ; SEE IF MASKER IS ALIVE. ; FIRST JUST SEE IF MASK FIELD IS SOMEWHAT READABLE. ALU [D] D [CONST 0] COND [-OBUS=0] JUMP [.] $ ALU [D] D [CONST 77] COND [OBUS=0] JUMP [.] $ ; NOW SEE IF MASKER CAN BE READ AT ALL ALU [D] D [MASK 0] COND [-OBUS=0] JUMP [.] $ ; FIRST TRY A ZERO MASK ALU [D] D [MASK 44] COND [OBUS=0] JUMP [.] $ ; TRY -1 MASK. HALTS IF ITS A ZERO ALU [NOTD] D [MASK 44] COND [-OBUS=0] JUMP [.] $ ; TRY -1 MASK. COMPLEMENT RESULT TO MAKE SURE ITS -1 ; NOW TRY LOADING VARIOUS REGISTERS TO SEE IF THEY ARE ALIVE AT ALL ALU [0] DEST [AR] $ ; TEST AR ALU [D] D [AR] COND [-OBUS=0] JUMP [.] $ ALU [-1] DEST [AR] $ ALU [D] D [AR] COND [OBUS=0] JUMP [.] $ ALU [NOTD] D [AR] COND [-OBUS=0] JUMP [.] $ ALU [0] DEST [MA] $ ;TEST MA ALU [D] D [MA] COND [-OBUS=0] JUMP [.] $ ALU [-1] DEST [MA] $ ALU [D] D [MA] COND [OBUS=0] JUMP [.] $ ; (CAN'T DO 'NOTD' THING YET SINCE MA NOT A 36 BIT REG, AND ; WE DON'T YET KNOW IF THE MASKER IS WORKING THAT WELL! ) ALU [0] DEST [HOLD] $ ; TEST HOLD REG ALU [D] D [MEM] COND [-OBUS=0] JUMP [.] $ ALU [-1] DEST [HOLD] $ ALU [D] D [MEM] COND [OBUS=0] JUMP [.] $ ALU [NOTD] D [MEM] COND [-OBUS=0] JUMP [.] $ ALU [0] DEST [CRYOV] $ ; LOAD ALL FLAGS IN PC WORD ALU [0] DEST [PC] $ ; ZERO THE PC ALU [D] D [PC] COND [-OBUS=0] JUMP [.] $ ; MAKE SURE FLAGS,,PC = 0 ALU [-1] DEST [PC] $ ALU [D] D [PC] COND [OBUS=0] JUMP [.] $ ; SHOULD BE NONZERO NOW ALU [-1] DEST [CRYOV] $ ALU [D] D [PC] COND [OBUS=0] JUMP [.] $ ; SHOULD STILL BE NONZERO ALU [0] DEST [PC] $ ALU [D] D [PC] COND [OBUS=0] JUMP [.] $ ; THERE SHOULD STILL BE FLAGS ON ALU [0] DEST [CRYOV] $ ; LEAVE IT ZERO, IN CASE OF ? ; ITS ABOUT TIME TO CHECK OUT THE CONSTANT (=MASK) FIELD THOROUGHLY. ALU [0] DEST [Q] $ ALU [Q+1] DEST [Q] $ ; SET Q=1 ; TRY A BIT IN ALL POSITIONS. XX = 1 .REPEAT 6 [ D [CONST XX] ALU [Q#D] COND [-OBUS=0] JUMP [.] $ XX = XX * 2 ALU [LSHQ] $ ] ; NOW MAKE SURE THE MASKER CAN BE OPERATED FROM THE MASK FIELD ALU [0] DEST [Q] $ XX = 0 .REPEAT 44 [ D [MASK XX] ALU [Q#D] COND [-OBUS=0] JUMP [.] $ ALU [LSHQ] $ ALU [Q+1] DEST [Q] $ XX = XX + 1 ] ; *** SOME BRUTE FORCE REGISTER DATA TESTS *** ; FIRST TEST AR REGISTER (BY COMPARING CONTENTS WITH Q REG) ; LONELY BIT IN ALL POSITIONS: D [CONST 1] DEST [Q] $ L3: ALU [Q] DEST [AR] $ ALU [Q#D] D [AR] COND [-OBUS=0] JUMP [.] $ ; COMPARE Q TO AR ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L3 $ ; LOOP UNTIL BIT FALLS OFF ; LONELY HOLE IN ALL POSITIONS: D [CONST 1] DEST [Q] $ L4: ALU [NOTQ] DEST [AR] $ ALU [D/#Q] D [AR] COND [-OBUS=0] JUMP [.] $ ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L4 $ ; LOOP UNTIL BIT FALLS OFF ; NOW TEST OUT THE HOLD REGISTER ; FIRST, LONELY BIT: D [CONST 1] DEST [Q] $ L5: ALU [Q] DEST [HOLD] $ ALU [D#Q] D [MEM] COND [-OBUS=0] JUMP [.] $ ; COMPARE Q TO HOLD ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L5 $ ; LOOP UNTIL BIT FALLS OFF. ; NOW, LONELY HOLE: D [CONST 1] DEST [Q] $ L6: ALU [NOTQ] DEST [HOLD] $ ALU [D/#Q] D [MEM] COND [-OBUS=0] JUMP [.] $ ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L6 $ ; NOW A MORE THOROUGH MASKER/ROTATOR TEST... ; FIRST GIVE THE ROTATOR A GOOD SHAKE ; THE FIRST TEST TRIES A LONELY BIT ROTATED TO ALL POSITIONS ; NOTE THAT CERTAIN REGISTERS (AR, HOLD) ARE ASSUMED TO WORK IN ORDER TO ; TEST THE ROTATOR. THEY SHOULD WORK DUE TO THE ABOVE TESTS. ; THE FOLLOWING ROTATOR TESTS USE THE ROT SIZE REGISTER, WITH VALUES ; FROM 1 TO 35. ; ROTATED BIT TEST: ALU [0] DEST [Q AR] $ ALU [Q+1] DEST [Q] $ ; SET Q=1. Q USED FOR COMPARISON IN LOOP ALU [Q] DEST [HOLD] $ ; SET HOLD=1. WILL BE DATA FOR THE TEST. L1: D [AR] DEST [ROTR] $ ; LOAD ROTATION COUNT REGISTER D [MEM] ROT [R] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ; COMPARE ROTATED BIT TO CONTENTS OF Q. ALU [D+1] D [AR] DEST [AR] $ ; INCREMENT ROTATE COUNTER ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L1 $ ; KEEP LOOPING UNTIL BIT GETS SHIFTED OFF XEND OF Q ; NOW TRY A ROTATING LONELY HOLE ALU [0] DEST [Q AR] $ ALU [Q+1] DEST [Q] $ ; SET Q=1 ALU [-1] DEST [HOLD] $ ; USE HOLD FOR DATA, SINCE ITS 36 BITS. ALU [D-1] D [MEM] DEST [HOLD] $ ;INIT HOLD TO -2 L2: D [AR] DEST [ROTR] $ ; LOAD ROTATION COUNT REGISTER D [MEM] ROT [R] ALU [D/#Q] COND [-OBUS=0] JUMP [.] $ ALU [D+1] D [AR] DEST [AR] $ ; INCREMENT SHIFT COUNT ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L2 $ ; KEEP LOOPING UNTIL BIT GETS SHIFTED OFF XEND OF Q ; NOW WE TRY OUT THE MASK GENERATOR, USING THE MASK SIZE REGISTER. ALU [0] DEST [Q HOLD] $ ; INITIALIZE L7: D [MEM] DEST [MASKR] $ ; LOAD MASK REGISTER D [2] MASK [R] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ; SEE IF MASK MATCHES CONTENTS OF Q. ALU [NOTQ] COND [OBUS=0] JUMP L7X $ ; EXIT FROM LOOP WHEN DONE. ALU [D+1] D [MEM] DEST [HOLD] $ ; INCREMENT MASK SIZE ALU [LSHQ] $ ALU [Q+1] DEST [Q] JUMP L7 $ ; ADD ONE TO Q. THIS MAKES Q INTO A MASK ; THEN LOOP L7X: ; NOW DO THE SAME TEST, BUT ACTUALLY USING THE MASKER AS WELL AS THE ; MASK GENERATOR. ALU [0] DEST [Q HOLD] $ ; INITIALIZE ALU [-1] DEST [AR] $ ; USE AR TO HOLD TEST DATA L8: D [MEM] DEST [MASKR] $ ; LOAD MASK REGISTER D [AR] ALU [D#Q] MASK [R] COND [-OBUS=0] JUMP [.] $ ; SEE IF MASKED DATA MATCHES CONTENTS OF Q. ALU [NOTQ] COND [OBUS=0] JUMP L8X $ ; EXIT FROM LOOP WHEN DONE. ALU [D+1] D [MEM] DEST [HOLD] $ ; INCREMENT MASK SIZE ALU [LSHQ] $ ALU [Q+1] DEST [Q] JUMP L8 $ ; ADD ONE TO Q. THIS MAKES Q INTO A MASK ; THEN LOOP L8X: ; OK, NOW THE MASKER AND ROTATOR ARE KNOWN TO BE AT LEAST REASONABLY HEALTHY. ; NOW WE CAN USE THEM TO TEST THE OTHER REGISTERS. ; *** MORE REGISTER TESTS *** ; TEST PC ; LONELY BIT TEST D [CONST 1] DEST [Q] $ L9: ALU [Q] DEST [PC] $ D [PC] ALU [D#Q] MASK [22] COND [-OBUS=0] JUMP [.] $ ; COMPARE PC TO Q, HANG UP IF NOT THE SAME ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L9 $ ; LOOP WHILE BIT IS IN RIGHT HALF OF Q. ; LONELY HOLE TEST D [CONST 1] DEST [Q] $ L10: ALU [NOTQ] DEST [PC] $ D [PC] ALU [D/#Q] DEST [HOLD] $ D [MEM] MASK [22] COND [-OBUS=0] JUMP [.] $ ; COMPARE PC WITH Q ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L10 $ ; LOOP WHILE BIT IS IN RIGHT HALF OF Q. ; THE PC STILL NEEDS TO BE TESTED FOR INCREMENTING PROPERLY, BUT THAT CAN WAIT. ; TEST MA (LOW ORDER 18. BITS ANYWAY; THIS IS A F2/F3 INCOMPATIBILITY) ; LONELY BIT TEST D [CONST 1] DEST [Q] $ L11: ALU [Q] DEST [MA] $ D [MA] ALU [D#Q] MASK [22] COND [-OBUS=0] JUMP [.] $ ; COMPARE MA TO Q, HANG UP IF NOT THE SAME ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L11 $ ; LOOP WHILE BIT IS IN RIGHT HALF OF Q. ; LONELY HOLE TEST D [CONST 1] DEST [Q] $ L12: ALU [NOTQ] DEST [MA] $ D [MA] ALU [D/#Q] DEST [HOLD] $ D [MEM] MASK [22] COND [-OBUS=0] JUMP [.] $ ; COMPARE MA WITH Q ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L12 $ ; LOOP WHILE BIT IS IN RIGHT HALF OF Q. ; NOW A TEST OF THE IR (GULP) ALU [0] DEST [HOLD] $ ; THIS PRESUMABLY WORKS BY NOW. ALU [0] DEST [IR-ALL] $ ALU [D] D [IR] COND [-OBUS=0] JUMP [.] $ ALU [-1] DEST [IR-ADR] $ ALU [D] D [IR] COND [OBUS=0] JUMP [.] $ ALU [-1] DEST [HOLD] $ ALU [D] D [IR] COND [OBUS=0] JUMP [.] $ ALU [0] DEST [IR-ALL] $ ; NOTE: THIS DOES NOT ZERO IR! JUST RIGHT HALF ALU [D] D [IR] COND [OBUS=0] JUMP [.] $ ALU [0] DEST [HOLD] $ ALU [0] DEST [IR-ADR] $ ; STILL SHOULDN'T ZERO THE IR ALU [D] D [IR] COND [OBUS=0] JUMP [.] $ ALU [0] DEST [IR-ALL] $ ; THIS ZEROS IT. ALU [D] D [IR] COND [-OBUS=0] JUMP [.] $ ALU [-1] DEST [HOLD] $ ALU [0] DEST [IR-23] $ ; THIS SHOULD UN-ZERO THE IR AGAIN ALU [D] D [IR] COND [OBUS=0] JUMP [.] $ ; NOW TEST THE IR MORE CAREFULLY D [CONST 1] DEST [Q] $ ALU [0] DEST [HOLD] $ L15: ALU [Q] DEST [IR-ALL] $ D [IR] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L15 $ L16: ALU [Q] DEST [HOLD] $ ;AT THIS POINT Q=1,,0 ALU [0] DEST [IR-ALL] $ D [IR] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ D [MEM] ROT [1] DEST [HOLD] $ ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L16 $ ; NOW THE LEGENDARY HOLE TEST... D [CONST 1] DEST [Q] $ ALU [-1] DEST [HOLD] $ L17: ALU [NOTQ] DEST [IR-ALL] $ ; LOADS IR WITH HOLE IN RIGHT HALF D [IR] ALU [D/#Q] COND [-OBUS=0] JUMP [.] $ ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L17 $ L18: ALU [NOTQ] DEST [HOLD] $ ;AT THIS POINT Q=1,,0 ALU [-1] DEST [IR-ALL] $ ; LOADS IR WITH HOLE IN LEFT HALF D [IR] ALU [D/#Q] COND [-OBUS=0] JUMP [.] $ D [MEM] ROT [1] DEST [HOLD] $ ; SHIFT THE HOLE LEFT ALU [LSHQ] $ ALU [Q] COND [-OBUS=0] JUMP L18 $ ; *** TEST AC SELECTION *** ; FIRST, LOAD EACH AC WITH ITS ADDRESS. XX = 0 .REPEAT 20 [ D [CONST XX] ROT 27 DEST [HOLD] $ ;MOVE AC# INTO HOLD REG DEST [IR-ALL] $ ;LOAD IR (ESP AC FIELD) ACSEL [AC] D [CONST XX] DEST [AC] $ ;STORE AC# IN AC XX = XX + 1 ;INC. AC # ] ; NEXT, TRY READING THEM BACK: USE ALL POSSIBLE MEANS OF ADDRESSING ; FIRST, USE AC FIELD OF IR: XX = 0 .REPEAT 20 [ D [CONST XX] ROT 27 DEST [HOLD] $ DEST [IR-ALL] $ ACSEL [AC] ALU [D#AC] D [CONST XX] COND [-OBUS=0] JUMP [.] $ ; CHECKS TO MAKE SURE EACH AC CONTAINS ITS NUMBER. XX = XX + 1 ] ; 2ND, USE INDEX FIELD OF IR XX = 0 .REPEAT 20 [ D [CONST XX] ROT 22 DEST [HOLD] $ ; LOAD INDEX FIELD DEST [IR-ALL] $ ACSEL [MA] OP [R#S] SOURCE [D,A] D [CONST XX] COND [-OBUS=0] JUMP [.] $ ; ACSEL MA => 'A' ADDRESS COMES FROM INDEX FIELD OF IR. XX = XX + 1 ] ; 3RD, USE LOW ORDER BITS OF MA XX = 0 .REPEAT 20 [ D [CONST XX] DEST [MA] $ ; LOAD MA WITH AC # ACSEL [MA] ALU [AC] DEST [Q] $ ; LOAD Q WITH (AC) D [CONST XX] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ; COMPARE Q (=AC) WITH AC # XX = XX + 1 ] ; LAST, USE AC CNT REGISTER XX = 0 ALU [0] DEST [AC-SEL] $ .REPEAT 20 [ D [CONST XX] ACSEL [REG] DEST [A-MEM-CNTR&INC] ALU [D#AC] COND [-OBUS=0] JUMP [.] $ XX = XX + 1 ] ; **** NOW TEST A-MEM **** ; FIRST A SPOT CHECK USING LITERAL ADDRESSING ; WRITE BLOCK NUMBER + 1 IN ZEROTH WORD OF EACH 8-WORD BLOCK IN A-MEM D [CONST 40] DEST [Q CLR-DEV-FROM-INTR] $ L40: ALU [Q-1] DEST [DEV-ADR] $ ALU [Q] DEST [0] SPEC [DEST-A-MEM] $ ALU [Q-1] DEST [Q] COND [-OBUS=0] JUMP L40 $ ; NOW TRY READING IT BACK D [CONST 40] DEST [Q] $ L41: ALU [Q-1] DEST [DEV-ADR] $ D [10] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ALU [Q-1] DEST [Q] COND [-OBUS=0] JUMP L41 $ ; WRITE NOT(BLOCK NUMBER+1) IN FOURTH WORD OF EACH 8-WORD BLOCK IN A-MEM D [CONST 40] DEST [Q CLR-DEV-FROM-INTR] $ L42: ALU [Q-1] DEST [DEV-ADR] $ ALU [NOTQ] DEST [4] SPEC [DEST-A-MEM] $ ALU [Q-1] DEST [Q] COND [-OBUS=0] JUMP L42 $ ; NOW TRY READING IT BACK D [CONST 40] DEST [Q] $ L43: ALU [Q-1] DEST [DEV-ADR] $ D [14] ALU [D/#Q] COND [-OBUS=0] JUMP [.] $ ALU [Q-1] DEST [Q] COND [-OBUS=0] JUMP L43 $ ;;Special A-MEM addressing test suggested by TVR, adapted to fact that each ;;12-bit chunk of 36-bit A-MEM word is on separate card. MLB 15 NOV 79 ;The following 12-bit pattern is triplicated in each word of A-MEM: ; 00 01 02 03 04 05 06 07 08 09 10 11 ;BITS: 12 13 14 15 16 17 18 19 20 21 22 23 ; 24 25 26 27 28 29 30 31 32 33 34 35 ; !----|----|----!----|----|----!----|----|----!----|----|----! ; ! comp. word ! word ! 0 | 8 wd block number / ! ; ! number ! number ! | device address ! ; !----|----|----!----|----|----!----|----|----!----|----|----! ; (eg word number 5 in block 16 contains 251625162516) ;This routine keeps a copy of the 12-bit pattern in AR and uses Q as a temp. ALU[0] DEST[Q CLR-DEV-FROM-INTR] $ ;Init Q, clear dev num AMWLP: ;Loop to write pattern into A-MEM, Q has device number at this point AMWORD = 0 .REPEAT 8 [ ;For each word create pattern and write it D[CONST 7 * ( 8 - AMWORD ) ] ;This gives comp-word:word num ROT[6] ALU[DORQ] DEST[Q AR] $ ;Q AR _ 12-bit pattern D[AR] ROT[14] ALU[DORQ] DEST[Q DEV-ADR] $ ;copy patt, set dev num D[AR] ROT[30] ALU[DORQ] DEST[AMWORD] SPEC[DEST-A-MEM] $ ;Write full pattern into A-MEM D[AR] MASK[37] ALU[Q] DEST[Q] $ ;Q _ just device number AMWORD = AMWORD + 1 ] ALU[Q+1] DEST[Q CLR-DEV-FROM-INTR] $ ;Incr Q for next device D[CONST 37] ALU[D&Q] DEST[Q] ;Mask to get device number COND[-OBUS=0] JUMP AMWLP $ ;Loop if not all dev nums done AMRLP: ;Loop to read and test pattern in A-MEM, Q has device number here AMWORD = 0 .REPEAT 8 [ ;For each word recreate pattern and test it against A-MEM D[CONST 7 * ( 8 - AMWORD ) ] ;This gives comp-word:word num ROT[6] ALU[DORQ] DEST[Q AR] $ ;Q AR _ 12-bit pattern D[AR] ROT[14] ALU[DORQ] DEST[Q DEV-ADR] $ ;copy patt, set dev num D[AR] ROT[30] ALU[DORQ] DEST[Q] $ ;Q _ 36-bit pattern D[10 + AMWORD] ALU[D#Q] COND[-OBUS=0] JUMP[.] $ ;HANGS HERE ON LOSSAGE D[AR] MASK[37] ALU[Q] DEST[Q] $ ;Q _ just device number AMWORD = AMWORD + 1 ] ALU[Q+1] DEST[Q CLR-DEV-FROM-INTR] $ ;Incr Q for next device D[CONST 37] ALU[D&Q] DEST[Q] ;Mask to get device number COND[-OBUS=0] JUMP AMRLP $ ;Loop if not all dev nums done ; NOW AN EXTENSIVE TEST USING THE AC CNT REG. ; WRITE BLOCKNUM,,WORDNUM INTO EACH WORD OF A-MEM ; BLOCKNUM IS NUMBER OF NTH 16.-WORD BLOCK ; WORDNUM IS INDEX OF WORD IN BLOCK D [CONST 17] DEST [AR CLR-DEV-FROM-INTR] $ ;INIT BLOCKNUM L20: D [AR] ROT [1] DEST [DEV-ADR] $ ; LOAD DEV ADR ALU [0] DEST [Q AC-SEL] $ ;INIT WORDNUM L200: D [AR] ROT [22] ALU [DORQ] DEST [A-MEM-CNTR&INC] SPEC [DEST-A-MEM] $ ;AMEM = BLK,,WORD ALU [Q+1] DEST [Q] $ D [CONST 20] ALU [D#Q] COND [-OBUS=0] JUMP L200 $ D [AR] COND [OBUS=0] JUMP L20X $ D [AR] ALU [D-1] DEST [AR] JUMP L20 $ L20X: ; NOW TRY TO READ IT BACK D [CONST 17] DEST [HOLD] $ ;INIT BLOCKNUM L21: D [MEM] ROT [1] DEST [DEV-ADR] $ ;LOAD DEV ADR REG ALU [0] DEST [Q AC-SEL] $ ;INIT WORDNUM L210: D [MEM] ROT [22] ALU [DORQ] DEST[Q] $ ;Q=BLK,,WORD DEST [AR A-MEM-CNTR] D [10] $ ;AR =A-MEM (AC CNT) D [AR] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ;COMPARE Q TO AR ALU [-1] SPEC [DEST-A-MEM] DEST [A-MEM-CNTR&INC] $ ;OVERWRITE A-MEM DATA TO MAKE TEST HARDER! D [MASK 22] ALU [D&Q] DEST [Q] $ ;Q=WORD ALU [Q+1] DEST [Q] $ ;Q=Q+1 D [CONST 20] ALU [D#Q] COND [-OBUS=0] JUMP L210 $ ;Q=20? D [MEM] COND [OBUS=0] JUMP L21X $ D [MEM] ALU [D-1] DEST [HOLD] JUMP L21 $ L21X: ; **** NOW TEST SOME OF THE "SPECIAL" FUNCTIONS **** ; MAKE SURE SPEC [MA_PC] WORKS... D [CONST 1] DEST [Q] $ L50: ALU [Q] DEST [PC] $ ALU [0] DEST [MA] SPEC [MA_PC] $ D [MA] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L50 $ D [CONST 1] DEST [Q] $ L51: ALU [NOTQ] DEST [PC] $ ALU [0] DEST [MA] SPEC [MA_PC] $ D [MA] ALU [D/#Q] DEST [HOLD] $ D [MEM] MASK [22] COND [-OBUS=0] JUMP [.] $ ALU [LSHQ] $ D [MASK 22] ALU [D&Q] COND [-OBUS=0] JUMP L51 $ ; TEST SPEC [LEFT] ; (FORCES MASK=-1,,0) D [MASK 0] SPEC [LEFT] ROT [22] DEST [Q] $ ;Q=777777, THE HARD WAY D [MASK 22] ALU [D#Q] COND [-OBUS=0] JUMP [.] $ ;NOW MAKE SURE ... ; TEST SPEC [PC+1] ALU [0] DEST [CRYOV] $ ALU [-1] DEST [PC] $ SPEC [PC+1] $ D [PC] COND [-OBUS=0] JUMP [.] $ SPEC [PC+1] $ D [PC] ALU [D-1] COND [-OBUS=0] JUMP [.] $ ; TEST MORE JUMP CONDITIONS: ; TRY OUT COND [AC=0] (TRUE IF IR AC=0) ; AND COND [MEM-IDX-IND] (TRUE IF IR IDX OR IND/=0) D [CONST 1] ROT [22] DEST [HOLD] $ .REPEAT 5 [ ALU [0] DEST [IR-ALL] $ COND [-AC=0] JUMP [.] $ COND [AC=0] JUMP [. + 2] $ JUMP [.] $ COND [MEM-IDX-IND] JUMP [. + 2] $ JUMP [.] $ COND [-MEM-IDX-IND] JUMP [.] $ D [MEM] ROT [1] DEST [HOLD] $ ] ; TEST BIT IN EACH POSITION OF IR AC FIELD .REPEAT 4 [ ALU [0] DEST [IR-ALL] $ COND [AC=0] JUMP [.] $ COND [-AC=0] JUMP [. + 2] $ JUMP [.] $ COND [MEM-IDX-IND] JUMP [.] $ COND [-MEM-IDX-IND] JUMP [. + 2] $ JUMP [.] $ D [MEM] ROT [1] DEST [HOLD] $ ] ; TEST COND [MA-AC] (NUMBER IN MA IS AN AC ADDR) ALU [0] DEST [MA] $ L60: COND [MA-AC] JUMP [. + 2] $ JUMP [.] $ COND [-MA-AC] JUMP [.] $ D [MA] ALU [D+1] DEST [MA Q] $ D [CONST 20] ALU [D#Q] COND [-OBUS=0] JUMP L60 $ ; AT THIS POINT MA=20 ; NOW ROTATE THE BIT INTO ALL POSITIONS, TO BE SURE THE CONDITION DOESNT ; BECOME TRUE SPURIOUSLY. L61: COND [MA-AC] JUMP [.] $ D [MA] ROT [1] DEST [MA Q] $ D [CONST 1] ALU [D#Q] COND [OBUS=0] JUMP [L61] $ ; NOW TRY ALL AC BITS ON, BUT EXTRA BITS ON TOO. D [CONST 20] DEST [Q] $ L62: D [CONST 17] ALU [DORQ] DEST [MA] $ COND [MA-AC] JUMP [.] $ COND [-MA-AC] JUMP [. + 2] $ JUMP [.] $ ALU [LSHQ] $ D [CONST 1] ROT[22] ALU [D&Q] COND [-OBUS=0] JUMP L62 $ ; TEST COND [OBUS18] D [CONST 1] ROT [21] COND [-OBUS18] JUMP [.] $ D [CONST 1] ROT [21] COND [OBUS18] JUMP [. + 2] $ JUMP [.] $ ALU [0] COND [OBUS18] JUMP [.] $ ALU [0] COND [-OBUS18] JUMP [. + 2] $ JUMP [.] $ ; TEST COND [OBUS<0] D [CONST 1] ROT [43] COND [-OBUS<0] JUMP [.] $ D [CONST 1] ROT [43] COND [OBUS<0] JUMP [. + 2] $ JUMP [.] $ ALU [0] COND [OBUS<0] JUMP [.] $ ALU [0] COND [-OBUS<0] JUMP [. + 2] $ JUMP [.] $ D [MASK 43] COND [OBUS<0] JUMP [.] $ D [MASK 43] COND [-OBUS<0] JUMP [. + 2] $ JUMP [.] $ .repeat 0 [ ;I'm afraid that's not what Q0-35 means. It has to do with shifting ; COND [Q0-35] LOW ORDER BIT OF Q REGISTER ALU [0] DEST [Q] $ ;FIRST TRY IT WITH A 0 COND [Q0-35] JUMP [.] $ COND [-Q0-35] JUMP [. + 2] $ JUMP [.] $ D [CONST 1] DEST [Q] $ ;THEN TRY IT WITH A 1 COND [Q0-35] JUMP [. + 2] $ JUMP [.] $ COND [-Q0-35] JUMP [.] $ ];repeat 0 ; COND[USER] ALU[0] DEST[CRYOV] NORM JUMP[. + 1] $ ;Clear all flags COND[-USER] NORM JUMP[. + 2] $ ;User on? JUMP[.] $ ;USER always true ALU[-1] DEST[CRYOV] NORM $ ;Try setting all flags COND[USER] NORM JUMP[. + 2] $ ;User on? JUMP[.] $ ;USER is never true D[CONST 1] ROT[44 - 6] DEST[CRYOV] NORM $ ;Now, try user bit itself COND[USER] NORM JUMP[. + 2] $ JUMP[.] $ ;USER is connected to wrong bit D[CONST 1] ROT[44 - 6] ALU[NOTD] DEST[CRYOV] NORM $ COND[-USER] NORM JUMP[. + 2] $ JUMP[.] $ ;USER is conditioned by something other than the user bit ; **** SEQUENCER TESTS **** ; CHECK OUT PUSHJ .REPEAT 5 [ JPOP [. + 1] $ ; MAKE DAMN SURE STACK IS EMPTY BEFORE TEST! ] ; THIS TEST MAKES SURE THE ROUTINE GETS CALLED EXACTLY THE RIGHT NUMBER ; OF TIMES. D [CONST 10] DEST [Q] $ .REPEAT 10 [ PUSHJ [ROUT1] $ ] ALU [Q] COND [-OBUS=0] JUMP [.] $ JUMP PJ $ ROUT1: ALU [Q-1] DEST [Q] POPJ $ JUMP [.] $ ; FURTHER PUSHJ CHECK... TRY NESTED ROUTINES. PJ: ALU [0] DEST [Q] $ PUSHJ R1 $ ALU [D#Q] D [CONST 37] COND [-OBUS=0] JUMP [.] $ JUMP LOOP0 $ R1: D [CONST 1] ALU [DORQ] DEST [Q] PUSHJ R2 $ POPJ $ JUMP [.] $ R2: D [CONST 2] ALU [DORQ] DEST [Q] PUSHJ R3 $ POPJ $ JUMP [.] $ R3: D [CONST 4] ALU [DORQ] DEST [Q] PUSHJ R4 $ POPJ $ JUMP [.] $ R4: D [CONST 10] ALU [DORQ] DEST [Q] PUSHJ R5 $ POPJ $ JUMP [.] $ R5: D [CONST 20] ALU [DORQ] DEST [Q] POPJ $ JUMP [.] $ ; CHECK LOOP, INCLUDING R REGISTER IN SEQUENCER, AND LLOAD LUPERR: JUMP [.] $ ; THE FIRST LOOP TEST COMES HERE IF IT LOSES ; THE PUSHJ TEST COMES HERE AFTER ITS DONE. LOOP0: ALU [0] DEST [Q] LLOAD $ ALU [Q-1] DEST [Q] LOOP [LUPERR] $ ; SHOULD JUST FALL THROUGH ALU [NOTQ] COND [-OBUS=0] JUMP [.] $ ; Q SHOULD BE -1 D [CONST 1] DEST [Q] LLOAD $ ; R=Q=1 ALU [Q-1] DEST [Q] LOOP [.] $ ALU [NOTQ] COND [-OBUS=0] JUMP [.] $ D [CONST 1] ROT [3] DEST [Q] LLOAD $ ; R=Q=10 ALU [Q-1] DEST [Q] LOOP [.] $ ALU [NOTQ] COND [-OBUS=0] JUMP [.] $ D [CONST 1] ROT [6] DEST [Q] LLOAD $ ; R=Q=100 ALU [Q-1] DEST [Q] LOOP [.] $ ALU [NOTQ] COND [-OBUS=0] JUMP [.] $ D [CONST 1] ROT [11.] DEST [Q] LLOAD $ ; R=Q=4000 ALU [Q-1] DEST [Q] LOOP [.] $ ALU [NOTQ] COND [-OBUS=0] JUMP [.] $ ; ;Test the MAP for its function as a memory ; ;Will it hold bits? ALU[0] DEST[MA CRYOV] NORM JUMP[. + 1] $ ;Use map location 0, EXEC space ALU[0] DEST[STO-MAP] NORM PUSHJ[MAPRD] $ ;See which bits stick on ALU[Q] COND[OBUS=0] JUMP[.] $ ;These bits should be zero. ;(Caution: Bit 9, NO MAP ENTRY, is inverted.) ALU[-1] DEST[STO-MAP] NORM PUSHJ[MAPRD] $ ;Set which bits don't come on D[MASK 22] ROT[9.] ALU[D#Q] JUMP[.] $ ;Bits shown here should be one, but read back as zero. ;(Caution: Bit 9, NO MAP ENTRY, is inverted.) D[CONST 1] ROT[44 - 5] DEST[CRYOV] NORM $ ;Try USER part of map ALU[0] DEST[STO-MAP] NORM PUSHJ[MAPRD] $ ;See which bits stick on in user map ALU[Q] COND[OBUS=0] JUMP[.] $ ;These bits should be zero. ;(Caution: Bit 9, NO MAP ENTRY, is inverted.) ALU[-1] DEST[STO-MAP] NORM PUSHJ[MAPRD] $ ;Set which bits don't come on in user map D[MASK 22] ROT[9.] ALU[D#Q] JUMP[.] $ ;Bits shown here should be one, but read back as zero. ;(Caution: Bit 9, NO MAP ENTRY, is inverted.) ;Simple addressing test ALU[0] DEST[Q MA CRYOV] NORM JUMP[. + 1] $ ;Start with a clear slate MPADL1: ALU[Q] DEST[STO-MAP] NORM $ ;Set contents to address D[CONST 1] ROT[9] ALU[D+Q] DEST[Q] $ ;Advance to next page D[MASK 22] ALU[D&Q] DEST[MA] NORM COND[-OBUS=0] JUMP[MPADL1] $ ;Check for XEND of EXEC/USER space D[CONST 1] ROT[44 - 9] DEST[CRYOV] SHORT $ ;Set user mode D[CONST 1] ROT[22] ALU[D#Q] COND[OBUS=0] JUMP[MPADL1] $ ;Jump if at XEND of EXEC pass ALU[0] DEST[Q MA CRYOV] NORM JUMP[. + 1] $ ;Start again, this time reading MPADL2: ALU[Q] DEST[AR] NORM PUSHJ[MAPRD] $ ;Save data and fetch map location D[AR] ALU[Q#D] NORM COND[-OBUS=0] JUMP[.] $ ;Lights show bits in error D[AR] DEST[Q] SHORT $ ;Restore Q D[CONST 1] ROT[9] ALU[D+Q] DEST[Q] $ ;Advance to next page D[MASK 22] ALU[D&Q] DEST[MA] COND[-OBUS=0] JUMP[MPADL2] $ ;Check for XEND of EXEC/USER space D[CONST 1] ROT[44 - 9] DEST[CRYOV] SHORT $ ;Set user mode D[CONST 1] ROT[22] ALU[D#Q] NORM COND[OBUS=0] JUMP[MPADL2] $ ;Jump if at XEND of EXEC pass ;Try single bits D[CONST 1,,1] DEST[AR] NORM JUMP[. + 1] MPBTL0: ALU[0] DEST[MA CRYOV] NORM JUMP[. + 1] $ MPBTL1: D[AR] ROT[1] MASK[22] DEST[AR] NORM $ ;Rotate right one, each half D[AR] ROT[9] DEST[STO-MAP] NORM $ ;Put single bit into map ;Note, extra bit from left half should have no effect D[CONST 1] ROT[9] ALU[D+Q] DEST[Q] SHORT $ D[MASK 22] ALU[D&Q] DEST[MA] NORM COND[-OBUS=0] JUMP[MPBTL1] $ ;Repeat for each map entry in this space D[AR] ROT[42] DEST[AR] NORM $ ;Backup to beginning of this iteration. (1024=18*57-2) ;Now, try reading it back ALU[0] DEST[MA CRYOV] NORM JUMP[. + 1] $ MPBTL2: D[AR] ROT[1] MASK[22] DEST[AR] NORM PUSHJ[MAPRD] $ ;Rotate right one, each half D[AR] ROT[9] ALU[D#Q] DEST[Q] SHORT $ ;Do comparison, ignore extra junk for the momemnt D[MASK 22] ROT[9] ALU[D&Q] NORM COND[-OBUS=0] JUMP[.] $ ;Bits in error show in lights. AR contains what ;it should be, ignoring bits 0:8, 27:35. Note: ;that bit 9 (NO MAP ENTRY) is complemented by map. D[MA] DEST[Q] $ D[CONST 1] ROT[9] ALU[D+Q] DEST[Q] SHORT $ D[MASK 22] ALU[D&Q] DEST[MA] NORM COND[-OBUS=0] JUMP[MPBTL2] $ ;Repeat for each map entry in this space D[CONST 1] ROT[44 - 9] DEST[CRYOV] COND[EXEC] JUMP[MPBTL2] $ ;Set user mode and repeat test if previously in exec. D[AR] ROT[43] DEST[AR Q] NORM $ ;Let AR rotated left one from previous iteration ;(1024=18*57-2, we're doing -1 this time) D[CONST 1,,1] ALU[D#Q] NORM COND[-OBUS=0] JUMP[MPBTL0] $ ;Repeat this test 18 times. ;Do lonesome holes D[CONST 1,,1] DEST[AR] NORM JUMP[. + 1] MPHLL0: ALU[0] DEST[MA CRYOV] NORM JUMP[. + 1] $ MPHLL1: D[AR] ROT[1] MASK[22] DEST[AR] NORM $ ;Rotate right one, each half D[AR] ROT[9] ALU[NOTD] DEST[STO-MAP] NORM $ ;Put single bit into map ;Note, extra bit from left half should have no effect D[CONST 1] ROT[9] ALU[D+Q] DEST[Q] SHORT $ D[MASK 22] ALU[D&Q] DEST[MA] NORM COND[-OBUS=0] JUMP[MPHLL1] $ ;Repeat for each map entry in this space D[AR] ROT[42] DEST[AR] NORM $ ;Backup to beginning of this iteration. (1024=18*57-2) ;Now, try reading it back ALU[0] DEST[MA CRYOV] NORM JUMP[. + 1] $ MPHLL2: D[AR] ROT[1] MASK[22] DEST[AR] NORM PUSHJ[MAPRD] $ ;Rotate right one, each half D[AR] ROT[9] ALU[D/#Q] DEST[Q] SHORT $ ;Do comparison, ignore extra junk for the momemnt D[MASK 22] ROT[9] ALU[D&Q] NORM COND[-OBUS=0] JUMP[.] $ ;Bits in error show in lights. AR contains complement ;of what it should be, ignoring bits 0:8, 27:35. ;Note that bit 9 (NO MAP ENTRY) is complemented by map. D[MA] DEST[Q] $ D[CONST 1] ROT[9] ALU[D+Q] DEST[Q] SHORT $ D[MASK 22] ALU[D&Q] DEST[MA] NORM COND[-OBUS=0] JUMP[MPHLL2] $ ;Repeat for each map entry in this space D[CONST 1] ROT[44 - 9] DEST[CRYOV] COND[EXEC] JUMP[MPHLL2] $ ;Set user mode and repeat test if previously in exec. D[AR] ROT[43] DEST[AR Q] NORM $ ;Let AR rotated left one from previous iteration ;(1024=18*57-2, we're doing -1 this time) D[CONST 1,,1] ALU[D#Q] NORM COND[-OBUS=0] JUMP[MPHLL0] $ ;Repeat this test 18 times. JUMP[MPTSTEND] ;Still need to be written: ; Test for CLR-MAP ; Tests page faults ;Subroutine to fetch map entry MAPRD: D[CONST 1] DEST[DEV-ADR] NORM SPEC[IOB-IN] $ ;Set to map and start a read MAPF[4] D[IOD] DEST[Q] CYLEN[IOB-IN] $ ;Read map at current MA D[CONST 1] ROT[44 - 9] ALU[D#Q] DEST[Q] SHORT $ ;Fix backward bit D[MASK 22] ROT[9] ALU[D&Q] DEST[Q] NORM POPJ $ ;Get rid of extra crud and return MPTSTEND: ;End of map test JUMP START $ ;Test USER/EXEC shift register ALU[0] DEST[Q AR MA] JUMP[. + 1] $ USRSH1: D[AR] ROT[9] DEST[MAP-EXEC-SR] $ ;Set USER shift register from OBUS D[CONST 4] LLOAD $ USRSH2: D[AR] MASK[1] NORM COND[-OBUS=0] JUMP[USRSH3] $ ;Jump if user expected COND[-USER] NORM JUMP[USRSH4] $ ;Should be in exec mode here JUMP[.] $ ;Failure in USER shift register. USRSH3: COND[USER] NORM JUMP[USRSH4] $ ;Should be in user mode here JUMP[.] $ ;Failure in USER shift register USRSH4: DEST[MEMSTO] NORM $ ;As a side effect, advances user shift register D[AR] ROT[43] MASK[4] NORM LOOP[USRSH2] $ ;Repeat for each position in shifter ALU[Q+1] DEST[Q AR] $ ;Try next case D[AR] MASK[4] COND[-OBUS=0] JUMP[USRSH1] $ ;Repeat for each pattern ;----------------------------------------------------------------------- ;This is a simple loop which copies the switches into the lights ;It is here so that it can be patched to make special purpose ;diagnostics, as well and providing a simple test for the switches, ;lights and the FBUS. ;----------------------------------------------------------------------- SWLOOP: ALU[0] DEST[DEV-ADR] NORM JUMP[. + 1] $ DEST[CLR-DEV-FROM-INTR] NORM SPEC[IOB-IN] $ ;Setup to read switches. Make sure we get them! MAPF[2] D[IOD] DEST[Q] CYLEN[IOB-IN] SPEC[IOB-IN] $ ;This gets the data switches, also get address switches MAPF[4] D[IOD] DEST[MA AR] CYLEN[IOB-IN] $ .REPEAT 20[ CONT $ ] ;Plenty of space for special hacks ALU[0] DEST[DEV-ADR] NORM JUMP[. + 1] $ ;Don't trust anyone! ALU[Q] DEST[IOD] NORM SPEC[IOB-OUT] $ ;Display results in lights. (Did you turn off SEE OBUS?) MAPF[2] ALU[Q] CYLEN[IOB-OUT] JUMP[SWLOOP] $ ]